// -----------------------------------------------------------------------------
// Copyright (c) 2014-2023 All rights reserved
// *********************************************************************************
// Project Name : stop_watch
// Author       : DFY
// File Name    : stop_watch.v
// Abstract     : 
 module stop_watch
 		#(parameter DIV_DEGREE = 10_000_000)(
    input               	clk,
    input               	rst_n,
    input               	clear,
    input               	start_stop, //has been posedge 
    output  reg [3:0]       hr_h,
    output  reg [3:0]       hr_l,
    output  reg [3:0]       min_h,
    output  reg [3:0]       min_l,
    output  reg [3:0]       sec_h,
    output  reg [3:0]       sec_l
 );
//=================================================================================
// Signal and Parameter declaration
//=================================================================================
wire sec_l_carry = (sec_l == 4'd9);
wire sec_h_carry = (sec_h == 4'd5) && sec_l_carry;
wire min_l_carry = (min_l == 4'd9) && sec_h_carry;
wire min_h_carry = (min_h == 4'd5) && min_l_carry;
wire hr_l_carry  = ( hr_l == 4'd9) && min_h_carry;
wire hr_h_carry  = ( hr_h == 4'd2) && (hr_l == 4'd3) && min_h_carry;
reg [15:0] clk_cnt;
reg        clk_out;
wire clk1HZ_pos;
//=================================================================================
// Body
//=================================================================================


always @ (posedge  clk or negedge rst_n)
	if(!rst_n)
		clk_cnt <= 16'b0;
	else if (clk_cnt == (DIV_DEGREE/2 -1))
		clk_cnt <= 16'b0;
	else
		clk_cnt <= clk_cnt + 1;

always @ (posedge  clk or negedge rst_n)
	if(!rst_n)
		clk_out <= 1'b0;
	else if (clk_cnt == (DIV_DEGREE/2 -1))
		clk_out <= ~clk_out;

assign clk1HZ_pos = (clk_cnt == DIV_DEGREE/2 -1) && (clk_out == 1'b0);
always @(posedge clk or negedge rst_n) begin 
	if(~rst_n) 
		sec_l <= 4'b0;
	else if (clear)
		sec_l <= 4'b0;
	else if (clk1HZ_pos&&start_stop)begin
		if(sec_l_carry)
			sec_l <= 4'd0;
		else
			sec_l <= sec_l + 1'b1;			
	end
end

always @(posedge clk or negedge rst_n) begin 
	if(~rst_n) 
		sec_h <= 4'b0;
	else if (clear)
		sec_h <= 4'b0;
	else if (clk1HZ_pos&&start_stop)begin
		if(sec_h_carry)
			sec_h <= 4'd0;
		else if(sec_l_carry)
			sec_h <= sec_h + 1'b1;			
	end
end

always @(posedge clk or negedge rst_n) begin 
	if(~rst_n) 
		min_l <= 4'b0;
	else if (clear)
		min_l <= 4'b0;
	else if (clk1HZ_pos&&start_stop)begin
		if(min_l_carry )
			min_l <= 4'd0;
		else if (sec_h_carry)
			min_l <= min_l + 1'b1;			
	end
end

always @(posedge clk or negedge rst_n) begin 
	if(~rst_n) 
		min_h <= 4'b0;
	else if (clear)
		min_h <= 4'b0;
	else if (clk1HZ_pos&&start_stop)begin
		if(min_h_carry)
			min_h <= 4'd0;
		else if (min_l_carry)
			min_h <= min_h + 1'b1;			
	end
end


always @(posedge clk or negedge rst_n) begin 
	if(~rst_n) 
		hr_l <= 4'b0;
	else if (clear)
		hr_l <= 4'b0;
	else if (clk1HZ_pos&&start_stop)begin
		if(hr_l_carry || hr_h_carry)
			hr_l <= 4'd0;
		else if (min_h_carry)
			hr_l <= hr_l + 1'b1;			
	end
end

always @(posedge clk or negedge rst_n) begin 
	if(~rst_n) 
		hr_h <= 4'b0;
	else if (clear)
		hr_h <= 4'b0;
	else if (clk1HZ_pos&&start_stop)begin
		if(hr_h_carry)
			hr_h <= 4'd0;
		else if (hr_l_carry)
			hr_h <= hr_h + 1'b1;			
	end
end
endmodule 
